/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (err) {
      this.reject(err)
    }
  }
  status = PENDING //状态
  value = undefined //成功的值
  reson = undefined //失败的原因
  successCallBack = [] //成功的回调
  failCallBack = [] //失败的回调
  resolve = value => {
    //如果状态是等待，程序向下执行
    if (this.status === PENDING) {
      //将状态更改为成功
      this.status = FULFILLED
      //保存成功的值
      this.value = value
      //判断成功函数是否存在，如果存在 调用
      while (this.successCallBack.length) {
        this.successCallBack.shift()()
      }
    }
  }
  reject = reson => {
    //如果状态是等待，程序向下执行
    if (this.status === PENDING) {
      //将状态更改为失败
      this.status = REJECTED
      //保存失败的原因
      this.reson = reson
      //判断失败函数是否存在，如果存在 调用
      while (this.failCallBack.length) {
        this.failCallBack.shift()()
      }
    }
  }
  then(successCallBack, failCallBack) {
    successCallBack = successCallBack ? successCallBack : value => value
    failCallBack = failCallBack ? failCallBack : reason => {
      throw reason
    }
    let promise2 = new MyPromise((resolve, reject) => {
      //判断状态执行对应的函数
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = successCallBack(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = failCallBack(this.reson)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else {
        //等待
        this.successCallBack.push(() => {
          setTimeout(() => {
            try {
              let x = successCallBack(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.failCallBack.push(() => {
          setTimeout(() => {
            try {
              let x = failCallBack(this.reson)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })
    return promise2
  }
  catch (failCallBack) {
   return this.then(undefined, failCallBack)
  } 
  finally(callback) {
    return this.then(value => {
      return MyPromise.resolve(callback()).then(value => value)
    }, reason => {
      return MyPromise.resolve(callback()).then(() => {
        throw reason
      })
    })
  }
  static all(array) {
    let result = []
    let index = 0
    return new MyPromise((resolve, reject) => {
      function addData(key, value) {
        result[key] = value
        index++
        if (index === array.length) {
          resolve(result)
        }
      }
      for (let i = 0; i < array.length; i++) {
        let current = array[i]
        if (current instanceof MyPromise) {
          //如果是promise对象
          current.then(
            value => addData(i, value),
            reason => reject(reason)
          )
        } else {
          addData(i, current)
        }
      }
    })
  }
  static resolve(value) {
    if (value instanceof MyPromise) {
      return value
    }
    return new MyPromise((resolve) => resolve(value))
  }
}
//判断x的值是普通纸还是promise对象
//如果是普通值 查看promise对象返回的结果
//如果是promise对象 查看promise对象返回的结果
//再根据对象返回的结果 决定调用resolve 还是调用reject
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof MyPromise) {
    x.then(resolve, reject)
  } else {
    resolve(x)
  }
}